package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.ExchangeConstants.ITEM_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKeyConstants.ITEM_DOWN_KEY;
import static com.leyou.common.constants.MQConstants.RoutingKeyConstants.ITEM_UP_KEY;

@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper , Spu> implements SpuService {

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SpuDetailService detailService;

    @Autowired
    private SkuService skuService;

    @Autowired
    private SpecParamService paramService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Override
    public PageDTO<SpuDTO> queryPageSpu(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
        //先判断页码数字是否正常
        if (page <= 0 || rows <= 0){
            throw new LyException(400 , "页码参数异常" );
        }
        //页面查询数据，多种条件查询
        Page<Spu> pages = query().eq(id != null, "id", id)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(brandId != null, "brand_id", brandId)
                .eq(saleable != null, "saleable", saleable)
                .page(new Page<>(page, rows));
        // 转换
        List<SpuDTO> spuDTOList = SpuDTO.convertEntityList(pages.getRecords());
        //对分类和品牌进行处理
        for (SpuDTO spuDTO : spuDTOList) {
            handleCategoryAndBrandName(spuDTO);
        }
        //返回
        return new PageDTO<>(pages.getTotal(),pages.getPages(),spuDTOList);

    }

    @Transactional
    @Override
    public void saveSpu(SpuDTO spuDTO) {
        // 1.新增spu
        //将spudto转换为spu
        Spu spu = spuDTO.toEntity(Spu.class);
        //在下架状态新增数据
        spu.setSaleable(false);
        //新增数据
        boolean issuccess = save(spu);
        //判断添加数据是否成功
        if (!issuccess){
            throw new LyException(500 , "新增商品失败");
        }
        //回显id,方便其他操作
        Long spuId = spu.getId();
        //2.新增spuDetail
        //获取spuDetail
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        //将spuDetailDTO转为spuDetail
        SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
        //新增spuid
        spuDetail.setSpuId(spuId);
        //新增spuDetail
        issuccess = detailService.save(spuDetail);
        //判断是否新增成功
        if (!issuccess){
            throw new LyException(500 , "新增商品失败");
        }
        //3.新增sku
        //获取skuDto
        List<SkuDTO> skuDTOSs = spuDTO.getSkus();
        //类型转换
        List<Sku> list = skuDTOSs.stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSpuId(spuId);
            sku.setSold(0L);
            sku.setSaleable(false);
            return sku;
        }).collect(Collectors.toList());
        //新增
        skuService.saveBatch(list);
    }

    @Transactional
    @Override
    public void updateSpu(SpuDTO spuDTO) {
        //1.修改spu
        if (spuDTO.getId() != null){
            //需要先数据转换
            Spu spu = spuDTO.toEntity(Spu.class);
            //只有在下架状态修改所以saleable不能改变
            spu.setSaleable(null);
            boolean ifSunccess = updateById(spu);
            //判断是否更新成功
            if (!ifSunccess){
                throw new LyException(500 ,"更新商品失败");
            }
        }
        //2.修改spuDetail
        //获取spuDetail
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        //判断是否修改如果spuIdhe和数据没有修改就跳过
        if (spuDetailDTO != null && spuDetailDTO.getSpuId() != null){
            //如果spuDetailDTO就修改
            SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
            boolean b = detailService.updateById(spuDetail);
            //判断是否更新成功
            if (!b){
                throw new LyException(500 ,"更新商品失败");
            }
        }
        //3.修改sku
        //获取sku集合
        List<SkuDTO> skuDTOS = spuDTO.getSkus();
        //看skuDtos是否有数据没有就跳过
        if (CollectionUtils.isEmpty(skuDTOS)){
            return;
        }
        //有的就修改
        //将skudtos集合进行类型转换
        Map<Boolean, List<Sku>> skuMap = skuDTOS.stream()
                .map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() != null));
        //获取需要删除的sku
        List<Sku> deleteSku = skuMap.get(true);
        if (!CollectionUtils.isEmpty(deleteSku)){
            //获取需要删除isku的id
            List<Long> deleteList  = deleteSku.stream()
                    .map(Sku::getId)
                    .collect(Collectors.toList());
            //删除
            skuService.removeByIds(deleteList);
        }
        //获取需要修改的sku
        List<Sku> saveAndUpdateSkuList = skuMap.get(false);
        //批量新增修改
        if (!CollectionUtils.isEmpty(saveAndUpdateSkuList)){
            saveAndUpdateSkuList.forEach(sku -> sku.setSaleable(false));
            skuService.saveOrUpdateBatch(saveAndUpdateSkuList);
        }
    }

    @Override
    @Transactional
    public void updateSaleable(Long id, Boolean saleable) {
        //新建一个spu对象
        Spu spu = new Spu();
        //将修改的id和saleable添加到空的spu对象
        spu.setId(id);
        spu.setSaleable(saleable);
        //修改是否上架
        boolean ifSuccess = updateById(spu);
        //判断是否修改成功
        if (!ifSuccess){
            throw new LyException( 500 ,"更新是否上架失败");
        }
        //修改sku中的是否删除
        //修改是否上架
        ifSuccess=skuService.update().set("saleable",saleable).eq("spu_id" ,id).update();
        //判断是否上架
        if (!ifSuccess){
            throw new LyException( 500 ,"更新是否上架失败");
        }
        //发送mq请求
        String routingKey = saleable ? ITEM_UP_KEY : ITEM_DOWN_KEY;
        amqpTemplate.convertAndSend( ITEM_EXCHANGE_NAME , routingKey ,id);
    }

    @Override
    public SpuDTO queryGoodsById(Long spuId) {
        //查询spu所有信息
        Spu spu = getById(spuId);
        //将查询到的spu放到spuDto
        SpuDTO spuDTO = new SpuDTO(spu);
        //查询spuDetail
        SpuDetailDTO spuDetailDTO =detailService.queryBySpuId(spuId);
        spuDTO.setSpuDetail(spuDetailDTO);
        //查询sku
        List<SkuDTO> list = skuService.queryBySpuId(spuId);
        spuDTO.setSkus(list);
        // 查询分类和品牌名称
        handleCategoryAndBrandName(spuDTO);
        //返回
        return spuDTO;
    }

    @Override
    public List<SpecParamDTO> queryParamBySpuIdAndSearching(Long spuId, Boolean searching) {
        //查询spu
        Spu spu = getById(spuId);
        //判断商品是否存在
        if (spu == null){
            throw new LyException(404 ,"商品不存在");
        }
        //获取规格参数第三级
        Long categoryId = spu.getCid3();
        //根据规格id查询规格参数
        List<SpecParamDTO> paramList = paramService.queryParam(categoryId, null, searching);
        //查询规格参数值
        SpuDetail spuDetail = detailService.getById(spuId);
        //获取规格参数json
        String specification = spuDetail.getSpecification();
        //将json格式转为map
        Map<Long, Object> specificationMap = JsonUtils.toMap(specification, Long.class, Object.class);
        //将规格参数放入SpecParamDTO
        for (SpecParamDTO paramDTO : paramList) {
            Object value = specificationMap.get(paramDTO.getId());
            paramDTO.setValue(value);
        }
        return paramList;
    }


    private void handleCategoryAndBrandName(SpuDTO spuDTO) {
        //获取三级id
        List<Long> categoryIds = spuDTO.getCategoryIds();
        //获取三级分类
        List<Category> categories = categoryService.listByIds(categoryIds);
        if (!CollectionUtils.isEmpty(categories)){
            //拼接分类名
            String name = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            //添加数据
            spuDTO.setCategoryName(name);
        }
        //获取品牌处理
        Long brandId = spuDTO.getBrandId();
        //根据品牌id查询品牌
        Brand brand = brandService.getById(brandId);

        if (brand != null){
            spuDTO.setBrandName(brand.getName());
        }
    }
}
